<?php

	if(!defined('YMT')) exit;

	define('GET', 'get');
	define('POST', 'post');
	define('SESSION', 'session');
	
	/**
	 * @package Yomm
	 * @author bsuter
	 *
	 */
	Class Yomm_Controller {
		
		/* env variables */
		public $get = null;
		
		public $post = null;
		
		public $session = null;
		
		public $db = null;
		
		public $theme = null;
		
		public $theme_full = null;
		
		public $view = null;
		
		public $i18n = null;
		
		/* controller atributes */
		public $compression = false;
		
		public $isAnonymus = null;
		
		public $isLogin = null;
		
		public $isLoginUrl = null;
		
		public $local = null;
		
		//public $cat_id = null;
		
		//public $lang = null;
		
		//public $nav = null;
		
		/**
		 * Yomm Controller Constructor; things to clean up in furder scripts:
		 * 
		 * TODO: after cleanup find dependences
		 * +=> 	$this->lang; will not be available in Framework (performe search for $this->lang)
		 * +=> 	$this->cat_id; makes no sense to do this check each time for all controllers with non cms functions. (performe serac hfor $this->cat_id)
		 * 		$this->cat_id = SiteConfig::DefaultCat; && $this->cat_id = $this->db->select("cms_cat", "id", "WHERE rewrite_link='{$this->get->cat}'", false)->id;
		 * +=> 	$this->nav = Navigation should be set only in CMS controller! old: $this->nav = $this->Navigation(); 'nav' => $this->nav, <= smarty assign $nav
		 * ==> 	smarty $this_cat should set only by cms controller old: 'this_cat' => $this->db->select("cms_cat", "rewrite_link", "WHERE id='{$this->cat_id}'", false)->rewrite_link,
		 * @return unknown_type
		 */
		public function __construct () {
			
			// write infos from get into session; so they will be available in the env variables
			// like: post,get,session
			$this->exec_before_session();
			
			// write env(ironement) variables:
			$this->get = $this->convertEnvVars($_GET);
			$this->post = $this->convertEnvVars($_POST);
			$this->session = $this->convertEnvVars($_SESSION);
			
			// make database connections
			$this->db = new Yomm_Db_Query();
			$this->db->connect(SiteConfig::SqlHost, SiteConfig::SqlUser, SiteConfig::SqlPass, SiteConfig::SqlDatabase);
			
			// set theme if noving is given befor class construction (could be used as extend class and define propertie protected $theme = XYZ)
			$this->setTheme($this->theme);
			
			// build the smarty view
			$this->view = new Yomm_View($this->theme);
			
			// set the multi lang settings
			$this->i18n = $this->db->select("cms_language", "*", "WHERE i18n='{$this->session->i18n}'", false);
			setlocale(LC_ALL, $this->i18n->i18n);
			
			$this->view->assign(array(
				'host' => SiteConfig::Domain,
				'theme' => $this->theme_full,
				'this_i18n' => $this->i18n->i18n,
				'languages' => $this->languages(),
				'i18n' => $this->i18n
			));
			
			$this->view->addJs(SiteConfig::Domain . 'share/js/config.php');
			$this->view->addJs(SiteConfig::Domain . 'share/js/prototype-min.js');
			$this->view->addJs(SiteConfig::Domain . 'share/js/avance-min.js');
			
			
			$this->securityRoleLoad();
			
			$this->local = Yomm_Library_Localization::getInstance($this->session->i18n);
		}
		
		public function setTheme ($theme = null) {
			// set theme if noving is given befor class construction (could be used as extend class and define propertie protected $theme = XYZ)
			if (is_null($theme)) {
				$this->theme = SiteConfig::ActiveTheme;
			} else {
				$this->theme = $theme;
			}
			
			$this->theme_full = SiteConfig::Domain . 'theme/' . $this->theme . '/';
			
			if (!is_null($this->view)) {
				$this->view->setTheme($this->theme);
				$this->view->assign('theme', $this->theme_full);
			}
		}
		
		/**
		 * convert environements variables into the requested object
		 * @param $var [array] values like $_POST or $_GET
		 * @return object
		 */
		private function convertEnvVars ($var) {
			if (!empty($var)) {
				$obj = null;
				foreach ($var as $key => $value) {
		            $obj->{$key} = $value;
		        }
		        return $obj;
		    }
		}
		
		/**
		 * returning values from environment super globals
		 * 
		 * @param $name [string] the name of the variable
		 * @param $env [string] use constants like GET, POST, SESSION to define from which environment the var should be grabbed
		 * @param $default [mixed] if the variable was not found what should be returned
		 * @param $type [string] variable type like: array, bool, float, int, null, numeric, object, string
		 * @return mixed
		 */
		protected function getVar ($name, $env, $default = null, $type = null) {
			// see if the values is set or not.
			if (!isset($this->{$env}->{$name})) {
				return $default;
			}
			// the variable is availabe so the in tmp var $var
			$var = $this->{$env}->{$name};
			// see if the check typed must be forced.
			if (!is_null($type)) {
				switch ($type) {
					case "mail":
						if (filter_var($var, FILTER_VALIDATE_EMAIL) === false) {
							return $default;
						}
						break;
					case "url":
						if (filter_var($var, FILTER_VALIDATE_URL) === false) {
							return $default;
						}
						break;
					default :
						$func = "is_{$type}";
						if (!$func($var)) {
							return $default;
						}
						break;
				}
			}
			
			return $var;
		}
		
		/**
		 * invoke a function for an array (or a string), there are two approaches to use this function:
		 * - APPROVAL:	if the invoke function returns BOOLEAN values the invoke function will return false 
		 * 				but will not response true, if the invoken function return true.
		 * - TRANSFORMATION:	the invoke function changes the value of the given $toBindArray (functions
		 * 						like ucfirst, strtolower, ucwords, ...) and returns the transformed array.
		 * 
		 * @param $toBindArray [mixed] can be an array or a string, best approach is to use associative array
		 * @param $invokeFunction [string] php functions like ucfirst, empty, strtoupper
		 * @param $invokeFunctionArgs [array] by default the function only contains the value of the given $toBindArray
		 * @return mixed
		 */
		protected function invoke ($toBindArray, $invokeFunction, $invokeFunctionArgs = array("%%value%%")) {
			// declare vars
			$output = array();
			$isStringOutput = false;
			// see of its an array or not
			if (!is_array($toBindArray)) {
				$toBindArray = array($toBindArray);
				$isStringOutput = true;
			}
			// foreach all the values in the array
			foreach ($toBindArray as $key => $value) {
				$args = array();
				// prepare and replace the %%value%% statements in the arguments with $value
				foreach($invokeFunctionArgs as $arg) {
					$args[] = str_replace("%%value%%", $value, $arg);
				}
				// call the function
				$return = call_user_func_array($invokeFunction, $args);
				// break and return if the function return is false,
				// if it false its an APPROVAL approach of using invoke
				if ($return === false) {
					return false;
				}
				// if $return is not false its en TRANSFORMATION approach
				$output[$key] = $return;
			}
			// because the input was not an array we have to fallback to string output instead return the array
			if ($isStringOutput) {
				return $output[0];
			}
			// return the transformed array
			return $output;
		}
		
		/**
		 * get multiples variables from the same ENV for multiple $names/$keys
		 * 
		 * @param $check_fields_array [array] an array of $names/$keys in the env variable
		 * @param $env [string] use constants like GET, POST, SESSION to define from which environment the var should be grabbed
		 * @param $default [mixed] if the variable was not found what should be returned
		 * @param $type [string] variable type like: array, bool, float, int, null, numeric, object, string
		 * @return array
		 */
		protected function getVarArray($check_fields_array, $env, $default = null, $type = null) {
			$tmp = array();
			foreach ($check_fields_array as $k => $v) {
				$tmp[$v] = $this->getVar($v, $env, $default, $type);
			}
			return $tmp;
		}
		
		/**
		 * this function provides the possibility to delete/unset a values in the post, get, session vars
		 * @param $type [char] post, get, session
		 * @param $var [mixed] the variable name 
		 * @return boolean
		 */
		protected function unsetVar($type, $var) {
			if (!is_array($var)) {
				if (isset($this->$type->$var)) {
					unset($this->$type->$var);
					return true;
				}
				return null;
			}
			
			foreach ($var as $item) {
				if (isset($this->$type->$item)) {
					unset($this->$type->$item);
				}
			}
			return true;
		}
		
		/**
		 * sett if one or more values are empty
		 * @param $mixed_value [mixed] can be a string or an array to check
		 * @return boolean
		 */
		protected function isEmpty ($mixed_value) {
			if (!is_array($mixed_value)) {
				$mixed_value[] = $mixed_value;
			}
			
			foreach($mixed_value as $k => $v) {
				if (!isset($v) || empty($v) || is_null($v) || $v === 0 || $v == "") {
					return true;
				}
			}

			return false;
		}
		
		/**
		 * set a variable in the controllers $this->session variable
		 * @param $key [string] the key of the session variable 
		 * @param $content [string] the content/value of the $key
		 * @return boolean
		 */
		protected function setSession($key, $content)
		{
			$_SESSION[$key] = $content;
			
			$this->session->{$key} = $content;
			
			return true;
		}
		
		private function exec_before_session()
		{
			if(isset($_GET['i18n'])) $_SESSION['i18n'] = $_GET['i18n'];
			
			if(empty($_SESSION['i18n'])) $_SESSION['i18n'] = SiteConfig::DefaultLanguage;
			
			// TODO: generated ajax verify salt and keys
		}
		
		private function languages()
		{
			$obj = $this->db->select("cms_language", "*", false, true); $return = array();
			
			foreach($obj as $item)
			{
				if(SiteConfig::RewriteLinks)
				{
					$link = SiteConfig::Domain . $item->i18n . '/';
				} else {
					$link = SiteConfig::Domain . '?i18n=' . $item->i18n;
				}
				
				$return[] = array(
					'title' => $item->name,
					'i18n' => $item->i18n,
					'link' => $link
				);
			}
			
			return $return;
		}
		
		protected function buildNavigation()
		{
			$catas = $this->db->select("cms_cat", array("rewrite_link", "id"), false, true);
			
			$return = array();
			
			foreach($catas as $item)
			{
				$obj = new Yomm_Library_CmsNavigation($this->session->i18n, $item->id);
				
				$return[$item->rewrite_link] = $obj->getElements();
			}
			
			if (isset($this->cat_id) && !empty($this->cat_id)) {
				$now_nav = new Yomm_Library_CmsNavigation($this->session->i18n, $this->cat_id);
			
				$return['this'] = $now_nav->getElements();
			}
			
			return $return;
		}
		
		/**
		 * check if this controller requires as session or not.
		 */
		private function securityRoleLoad()
		{
			// this is for page which must have a login only: Profilmgmt Controller
            if($this->isLogin === true)
            {
                // now check if the 
                if(!isset($this->session->user->id))
                {
                    header("location:" . SiteConfig::Domain . $this->isLoginUrl);
                }
            }
			
            // this is for pages which should not have already a session, cause they are already logged in: Register Controller
            if($this->isAnonymus === true)
            {
            	if(isset($this->session->user->id))
            	{
            		header("location" . SiteConfig::srvUrl);
            	}
            }
        }
		
		/**
		 * new ajax returnal function. 
		 * TODO: add strip slashes possibility or something like that
		 * @param object $mix
		 * @param object $json_encode [optional]
		 * @return string
		 */
		public function ajaxResponse($mix, $json_encode = true)
		{
			if($json_encode === true){
				return json_encode($mix);
			} else {
				return $mix;
			}
		}
		
		/**
		 * redirect a 301 moved permantly with php. there can't be any output befor!
		 */
		protected function redirect($url = false)
		{
			if($url === false)
				$url = SiteConfig::Domain;
				
			header('HTTP/1.1 301 Moved Permanently');
  			header('Location: ' . $url);
  			exit;
		}
		
	}